//
//  P1Client.m
//  LongOA
//
//  Created by 梁文朗 on 15/7/20.
//  Copyright (c) 2015年 耿用强. All rights reserved.
//

#import "P1Client.h"
#import "JSON.h"
#import "YYJSONHelper.h"
#import "ILJRequest.h"
#import "LJResponse.h"
#import "GCDAsyncSocket.h"

typedef void(^CompletionLoadHandle)(NSData *posts, NSError *error);
@implementation P1Client
{
    NSData*_allData;// json内容
    int _fileCnt;// 文件个数
    NSFileHandle* _file;
    
    BOOL _isWorking;
    GCDAsyncSocket *clientSocket;
    CompletionLoadHandle completBolck;
}

-(id) initWithIP:(NSString *)ip
         AndPort:(int)port
{
    self = [super init];
    _isWorking = NO;
    clientSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)];
    //[self->clientSocket setRunLoopModes:[NSArray arrayWithObject:NSRunLoopCommonModes]];
    NSError *error = nil;
    [self->clientSocket connectToHost:ip onPort:port withTimeout:-1 error:&error];
    if (error)
    {
        NSLog(@"connectToHost error %@",error);
        [self->clientSocket disconnect];
    }
    return self;
}

-(void)Doexecute:(ILJRequest*) request
        RspClass:(Class) rspClass
          andMsg:(NSString*)msg
         andView:(UIView*) vi
globalTimelinePostsWithBlock:(void (^)(id rsp))block
{
    _isWorking = YES;
    MBProgressHUD *hud=nil;
    if (vi!=nil) {
        for (MBProgressHUD *oldHud in  [MBProgressHUD allHUDsForView:vi]) {
            [oldHud hide:NO];
            [oldHud removeFromSuperview];
        }
        hud = [[MBProgressHUD alloc] initWithView:vi];
        if (msg.length!=0) {
            hud.labelText=msg;
        }
        [hud show:NO];
        hud.removeFromSuperViewOnHide = YES;
        if (vi!=nil) {
            [vi addSubview:hud];
        }
    }
    
    self->completBolck=^(NSData*data,NSError*error)
    {
        @try {
            if (!error) {
                id rslt = [data toModel:rspClass];
                NSLog(@"do block");
                if (block) {
                    if (hud) {
                        dispatch_async(dispatch_get_main_queue(), ^{
                            block(rslt);
                        });
                    }
                    else {
                        block(rslt);
                    }
                }
            }
            else
            {
                NSString* rsltJson =  [[NSString alloc ] initWithFormat:@"{\"ErrMsg\":\"%@\"}", @"连接异常"];
                id rslt = [rsltJson toModel:rspClass];
                if (block) {
                    if (hud) {
                        dispatch_async(dispatch_get_main_queue(), ^{
                            block(rslt);
                        });
                    }
                    else {
                        block(rslt);
                    }
                }
            }
        }
        @catch (NSException *exception) {
            //[Commend showAlert:@"数据解析有误"];
            NSString* rsltJson =  [[NSString alloc ] initWithFormat:@"{\"ErrMsg\":\"%@\"}", @"数据解析有误"];
            id rslt = [rsltJson toModel:rspClass];
            if (block) {
                if (hud) {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        block(rslt);
                    });
                }
                else {
                    block(rslt);
                }
            }
        }
        @finally {
            if (hud) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    NSLog(@"hud hiding");
                    [hud hide:YES];
                    [hud removeFromSuperview];
                    NSLog(@"hud hide");
                });
            }
            _isWorking = NO;
        }
    };
    
    NSString*jsonString=[request YYJSONString];
//    SBJsonWriter *writer = [[SBJsonWriter alloc] init];
//    jsonString=[writer stringWithObject:params];
    if (jsonString.length==0) {
        jsonString=@"{}";
    }
    NSString* apiname = [request GetApiName];
    NSLog(@"api:%@",apiname);
    jsonString=[NSString stringWithFormat:@"%@%@",apiname,jsonString];
    NSData *fileData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
    
    Byte bytes[1];
    bytes[0] = (Byte) 0x04;
    NSData *flag = [[NSData alloc] initWithBytes:bytes length:1];
    [self->clientSocket writeData:flag withTimeout:-1 tag:0];
    
    NSData*jsondataLenth=[self intToByteArray:(int)fileData.length];
    [self->clientSocket writeData:jsondataLenth withTimeout:-1 tag:0];
    
    [self->clientSocket writeData:fileData withTimeout:-1 tag:0];
    
    short command = 0;
    NSData *shortData = [self shortToByteArray:command];
    [self->clientSocket writeData:shortData withTimeout:-1 tag:0];
    [self->clientSocket readDataToLength:4 withTimeout:-1 tag:0];
    //[self->clientSocket readDataWithTimeout:-1 tag:0];
    NSLog(@"requestEnd:%@",apiname);
}

-(void)requestWithApiName:(NSString *)apiName
                   params:(NSMutableDictionary *)params 
                   andMsg:(NSString*)msg 
                   andView:(UIView*)vi 
                   globalTimelinePostsWithBlock:(void (^)(NSDictionary *posts, NSError *error))block
{
    
    _isWorking = YES;
    MBProgressHUD *hud=nil;
    if (vi!=nil) {
        for (MBProgressHUD *oldHud in  [MBProgressHUD allHUDsForView:vi]) {
            [oldHud hide:NO];
            [oldHud removeFromSuperview];
        }
        hud = [[MBProgressHUD alloc] initWithView:vi];
        if (msg.length!=0) {
            hud.labelText=msg;
        }
        [hud show:NO];
        hud.removeFromSuperViewOnHide = YES;
        if (vi!=nil) {
            [vi addSubview:hud];
        }
    }
    
    self->completBolck=^(NSData*data,NSError*error)
    {
        [hud hide:YES];
        [hud removeFromSuperview];
        if (!error) {
            @try {
                NSString*dataString=@"";
                
//                Byte *testByte = (Byte *)[data bytes];
//                Byte testByte2[[data length]-5];
//                for(int i=4;i<[data length]-1;i++)
//                {
//                    testByte2[i-4]=testByte[i];
//                }
//                NSData*datas= [[NSData alloc] initWithBytes:testByte2 length:[data length]-5];
                
//                LJResponse* rsp = [[LJResponse alloc] init];
//                rsp = [datas toModel:[rsp class]];
                
                dataString=[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
                NSLog(@"%@", dataString);
                NSDictionary*result=[dataString JSONValue];
                if (result==nil) {
                    if (block) {
                        NSError*error=[NSError new];
                        block(result,error);
                    }
                }
                else
                {
                    if (block) {
                        block(result,nil);
                    }
                }

            }
            @catch (NSException *exception) {
                [Commend showAlert:@"数据解析有误"];
            }
            @finally {
                
            }
        }
        else
        {
            if (block) {
                NSError*error=[NSError new];
                block(nil,error);
            }
        }        
        _isWorking = NO;
    };
       
    NSString*jsonString=nil;
    SBJsonWriter *writer = [[SBJsonWriter alloc] init];
    jsonString=[writer stringWithObject:params];
    if (jsonString.length==0) {
        jsonString=@"{}";
    }
    jsonString=[NSString stringWithFormat:@"%@%@",apiName,jsonString];
    NSData *fileData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
    
    Byte bytes[1];
    bytes[0] = (Byte) 0x04;
    NSData *flag = [[NSData alloc] initWithBytes:bytes length:1];
    [self->clientSocket writeData:flag withTimeout:-1 tag:0];
    
    NSData*jsondataLenth=[self intToByteArray:(int)fileData.length];
    [self->clientSocket writeData:jsondataLenth withTimeout:-1 tag:0];
    
    [self->clientSocket writeData:fileData withTimeout:-1 tag:0];
    
    short command = 0;
    NSData *shortData = [self shortToByteArray:command];    
    [self->clientSocket writeData:shortData withTimeout:-1 tag:0];
    
    [self->clientSocket readDataToLength:4 withTimeout:-1 tag:0];
    //[self->clientSocket readDataWithTimeout:-1 tag:0];
}

#pragma mark - AsyncSocketDelegate
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
    NSLog(@"didReadData%li, %li", tag, data.length);
    
    if (tag == 0) { // 读取json长度
        int _allDataLen = [self getLength:data];
        [self->clientSocket readDataToLength:_allDataLen withTimeout:-1 tag:1];
    }
    else if (tag == 1) { // 读取json
        _allData = data;
        [self->clientSocket readDataToLength:1 withTimeout:-1 tag:2];
    }
    else if (tag == 2) { // 读取文件数量
        _fileCnt = ((Byte*)[data bytes])[0];
        
        if (_fileCnt > 0) {
            [self->clientSocket readDataToLength:4 withTimeout:-1 tag:3];
        }
        else {
            NSError*error=nil;
            if (self->completBolck) {
                self->completBolck(_allData,error);
            }
        }
    }
    else if (tag == 3) { // 读取文件名长度
        int _allDataLen = [self getLength:data];
        [self->clientSocket readDataToLength:_allDataLen withTimeout:-1 tag:4];
    }
    else if (tag == 4) { // 读取文件名
        NSString* filename = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        filename = [self GetName:filename];
        
        NSArray* cachPath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
        NSString* cachePath = [cachPath objectAtIndex:0];
        filename = [cachePath stringByAppendingPathComponent:filename];
        
        if (![[NSFileManager defaultManager] fileExistsAtPath:filename]) {
            BOOL res = [[NSFileManager defaultManager] createFileAtPath:filename contents:nil attributes:nil];
            if (res) {
                NSLog(@"文件创建成功:%@", filename);
                _file = [NSFileHandle fileHandleForWritingAtPath:filename];
            }
            else {
                NSLog(@"文件创建失败:%@", filename);
                _file = nil;
            }
        }
        else {
            _file = nil;
        }
        
        [self->clientSocket readDataToLength:4 withTimeout:-1 tag:5];
    }
    else if (tag == 5) { // 文件长度
        int _allDataLen = [self getLength:data];
        [self->clientSocket readDataToLength:_allDataLen withTimeout:-1 tag:6];
    }
    else if (tag == 6) { // 文件内容
        // DONE: 将_buffer , _allDataLen长度的内容写入文件
        [_file writeData:data];
        [_file closeFile];
        _file = nil;
        
        _fileCnt --;
        if (_fileCnt > 0) {
            [self->clientSocket readDataToLength:4 withTimeout:-1 tag:3];
        }
        else {
            NSError*error=nil;
            if (self->completBolck) {
                self->completBolck(_allData,error);
            }
        }
    }
}

- (NSData*)intToByteArray:(int)nVal
{
    Byte bytes[4];

    bytes[3] = (Byte) ((nVal >> 24) & 0xFF);
    bytes[2] = (Byte) ((nVal >> 16) & 0xFF);
    bytes[1] = (Byte) ((nVal >> 8) & 0xFF);
    bytes[0] = (Byte) (nVal & 0xFF);
    NSData *newData = [[NSData alloc] initWithBytes:bytes length:4];
    
    return newData;
}

- (NSData*)shortToByteArray:(short)nVal
{
    Byte bytes[2];

    bytes[1] = (Byte) ((nVal >> 8) & 0xFF);
    bytes[0] = (Byte) (nVal & 0xFF);
    NSData *newData = [[NSData alloc] initWithBytes:bytes length:4];
    
    return newData;
}

- (int)getLength:(NSData*)data
{
    Byte*bytes=(Byte *)[data bytes];
    Byte chi[4];
    for (int a=0; a<4; a++)
    {
        chi[a]=bytes[a];
    }
    NSData *chidata=[NSData dataWithBytes:chi length:4];
    int code;
    [chidata getBytes:&code length:4];
    return code;
}

-(NSString*)GetName:(NSString*)name
{
    NSString* rslt = [name stringByReplacingOccurrencesOfString:@"/" withString:@"-"];
    return rslt;
}


#pragma mark - AsyncSocketDelegate

- (void)onSocket:(GCDAsyncSocket *)sock willDisconnectWithError:(NSError *)err
{
    NSLog(@"client willDisconnectWithError:%@",err);
}

- (void)onSocketDidDisconnect:(GCDAsyncSocket *)sock
{
    NSLog(@"onSocketDidDisconnect");
}

- (void)socket:(GCDAsyncSocket *)sender didConnectToHost:(NSString *)host port:(UInt16)port
{
    NSLog(@"client didConnectToHost");
}

- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
{
    
}

- (NSString *)dataToString:(NSData *)data
{
    return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}


- (void)onSocket:(GCDAsyncSocket *)sock didReadPartialDataOfLength:(NSUInteger)partialLength tag:(long)tag
{
    NSLog(@"%li",partialLength);
    
}

@end
